package top.ieei.demo.tftp;

import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;

/**
 * 此类存放TFTP选项信息，该信息设置在TFTP的读取和写入请求中<br>
 * @author xiecongshu
 */
public class Options extends Hashtable<Object, Object>
{
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 4760635740443363870L;
    
    /**
     * 选项tsize的占位符
     */
    public static final String TSIZE = "tsize";
    
    /**
     * 选项timeout的占位符
     */
    public static final String TIMEOUT = "timeout";
    
    /**
     * 选项blksize的占位符
     */
    public static final String BLKSIZE = "blksize";
    
    /**
     * <默认构造函数>
     */
    public Options()
    {
        super();
    }
    
    /**
     * <默认构造函数>
     * @param int initialCapacity 初始化容量
     */
    public Options(int initialCapacity)
    {
        super(initialCapacity);
    }
    
    /**
     * <默认构造函数>
     * @param map Map
     */
    public Options(Map<?, ?> map)
    {
        super(map);
    }
    
    /**
     * 检索对应选项，并返回该选项的Integer值
     * @param option 选项名称
     * @return integer 选项的值或-1
     */
    public int getIntValueByOption(String option)
    {
        String intStr = (String) get(option);
        if (intStr == null)
        {
            return -1;
        }
        
        try
        {
            Integer value = Integer.decode(intStr);
            return value.intValue();
        }
        catch (NumberFormatException e)
        {
            return -1;
        }
    }
    
    /**
     * 根据选项名称设置选项值
     * @param option name of the integer option to retrieve
     * @param value value of the option
     */
    public void setIntValueByOption(String option, int value)
    {
        put(option, new Integer(value).toString());
    }
    
    /**
     * 获取包中选项数据的大小
     */
    public int getOptionsSize()
    {
        int size = 0;
        if (hasOption(TIMEOUT))
        {
            size += TIMEOUT.length() + String.valueOf(getTimeout()).length()
                    + 2;
        }
        
        if (hasOption(TSIZE))
        {
            size += TSIZE.length() + String.valueOf(getTransferSize()).length()
                    + 2;
        }
        
        if (hasOption(BLKSIZE))
        {
            size += BLKSIZE.length() + String.valueOf(getBlockSize()).length()
                    + 2;
        }
        
        return size;
    }
    
    /**
     * 设置选项和值
     * 
     * @param option
     */
    public Object put(Object option, Object value)
    {
        if (!(option instanceof String))
        {
            return null;
        }
        
        if (!(value instanceof String))
        {
            return null;
        }
        
        option = ((String) option).toLowerCase(Locale.ENGLISH);
        return super.put(option, value);
    }
    
    /**
     * 获取超时时间，秒，定义在RFC2349
     * 
     * @return timeout 超时时间，单位秒，如果无此选项，返回-1
     */
    public int getTimeout()
    {
        return getIntValueByOption(TIMEOUT);
    }
    
    /**
     * 设置超时时间，单位秒，定义在RFC2349
     * 
     * @param timeout 超时时间，单位秒
     */
    public void setTimeout(int to)
    {
        setIntValueByOption(TIMEOUT, to);
    }
    
    /**
     * 获取传输大小选项值，定义在RFC2349
     * 
     * @return tsize 传输大小，单位bytes，如果无此选项，返回-1
     */
    public int getTransferSize()
    {
        return getIntValueByOption(TSIZE);
    }
    
    /**
     * 设置传输大小选项值，定义在RFC2349
     * 
     * @param tsize 传输大小，单位bytes
     */
    public void setTransferSize(int tsize)
    {
        setIntValueByOption(TSIZE, tsize);
    }
    
    /**
     * 获取每块数据传输大小选项值，定义在RFC2349
     * 
     * @return blksize 单位bytes
     */
    public int getBlockSize()
    {
        return getIntValueByOption(BLKSIZE);
    }
    
    /**
     * 设置每块数据传输大小选项值，定义在RFC2349
     * 
     * @param blksize 块大小，单位bytes
     */
    public void setBlockSize(int blksize)
    {
        setIntValueByOption(BLKSIZE, blksize);
    }
    
    /**
     * 检查是否包含给定的选择设置
     */
    public boolean hasOption(String name)
    {
        return (this.containsKey(name));
    }
    
}
